package com.hm.cms.service.api;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import com.hm.cms.auto.SystemEnvConfigProperties;
import com.hm.cms.domain.ArticleDomain;
import com.hm.cms.domain.QArticleDomain;
import com.hm.cms.domain.QTermTayRelationshipsDomain;
import com.hm.cms.domain.TermTayRelationshipsDomain;
import com.hm.cms.repository.ArticleRepository;
import com.hm.cms.repository.TermTayRelationshipsRepository;
import com.hm.cms.service.ArticleService;
import com.hm.cms.service.TermTaxonomyService;
import com.hm.cms.service.TermsService;
import com.hm.cms.su.BeanUtil;
import com.hm.cms.vo.HcmsHomePageVo;
import com.hm.cms.vo.HcmsPageBaseInfoVo;
import com.hm.cms.vo.HcmsTermTaxonomyVo;
import com.hm.cms.vo.HcmsTermsVo;
import com.hm.cms.vo.api.ApiArticleVo;
import com.hm.common.def.DataStatusDef;
import com.hm.common.exception.ErrorCode;
import com.hm.common.exception.ServiceException;
import com.hm.common.su.bean.PageInfo;
import com.hm.common.su.bean.PageInfo.PageInfoParam;
import com.hm.common.util.CommonUtil;
import com.hm.common.util.DateUtil;
import com.hm.common.util.EncryptUtil.Base64;
import com.hm.common.util.FileUtil;
import com.hm.common.util.FreemakUtil;
import com.querydsl.core.types.dsl.BooleanExpression;

import lombok.extern.slf4j.Slf4j;

/**
 * @author shishun.wang
 * @date 2017年11月30日 下午4:59:35
 * @version 1.0
 * @describe
 */
@Slf4j
@Service
public class ArticleApiServiceImpl implements ArticleApiService {

	private static int PAGE_SIZE = 1000;

	@Autowired
	private TaskExecutor taskExecutor;

	@Autowired
	private ArticleRepository articleRepository;

	@Autowired
	private SystemEnvConfigProperties systemEnvConfigProperties;

	@Autowired
	private TermTayRelationshipsRepository termTayRelationshipsRepository;

	@Autowired
	private TermsService termsService;

	@Autowired
	private ArticleService articleService;

	@Autowired
	private TermTaxonomyService termTaxonomyService;

	@Override
	public PageInfo<ApiArticleVo> query(PageInfoParam pageParam, boolean isStatic) {
		QArticleDomain qArticleDomain = QArticleDomain.articleDomain;
		Pageable pageable = new QPageRequest(pageParam.getPage(), pageParam.getSize(),
				qArticleDomain.createTime.desc());

		BooleanExpression predicate = qArticleDomain.status.eq(DataStatusDef.ENABLE);
		if (isStatic) {
			predicate = predicate.and(qArticleDomain.staticizeUri.isNotNull());
		} else {
			predicate = predicate.and(qArticleDomain.staticizeUri.isNull());
		}

		List<ApiArticleVo> vos = new ArrayList<ApiArticleVo>();
		Page<ArticleDomain> page = articleRepository.findAll(predicate, pageable);
		page.getContent().forEach(item -> {
			ApiArticleVo vo = new ApiArticleVo();
			BeanUtil.copyProperties(item, vo);
			vo.setCreateTime(DateUtil.data2long(item.getCreateTime()));
			vos.add(vo);
		});

		return new PageInfo<ApiArticleVo>(vos, page.getTotalPages(), page.getTotalElements());
	}

	@Override
	public void staticArticle(String articleId) {
		log.info("静态化文件:{}", articleId);
		if (CommonUtil.isEmpty(articleId)) {
			throw ServiceException.warning(ErrorCode.REQUIRED_PARAMETERS_MISSING);
		}

		TermTayRelationshipsDomain termTayRelationships = termTayRelationshipsRepository
				.findOne(QTermTayRelationshipsDomain.termTayRelationshipsDomain.articleId.eq(articleId.trim()));
		if (CommonUtil.isEmpty(termTayRelationships)) {
			throw ServiceException.warning(ErrorCode.DATA_NOT_FOUND);
		}

		Map<String, Object> model = new HashMap<String, Object>();
		{
			HcmsPageBaseInfoVo baseInfoVo = new HcmsPageBaseInfoVo();
			{
				baseInfoVo.setOpenLogin(systemEnvConfigProperties.isOpenLogin());
				baseInfoVo.setSiteFtInfo(
						new String(Base64.decode(systemEnvConfigProperties.getSiteFooterInfo().toCharArray())));
			}

			if (CommonUtil.isEmpty(termTayRelationships.getTermTayIds())) {
				log.warn("没找到标签模板{}", articleId);
				return;
			}
			HcmsTermTaxonomyVo hcmsTermTaxonomyVo = termTaxonomyService
					.getTermTaxonomysById(termTayRelationships.getTermTayIds().get(0));
			if (CommonUtil.isEmpty(hcmsTermTaxonomyVo)) {
				log.warn("没找到标签模板{}", articleId);
				return;
			}

			List<String> termIds = termTayRelationships.getTermIds();
			if (CommonUtil.isEmpty(termIds)) {
				log.error("没找到分类");
				return;
			}

			HcmsTermTaxonomyVo termTaxonomyVo = termTaxonomyService
					.getTermTaxonomysByCode(hcmsTermTaxonomyVo.getTermTayCode());
			model.put("termTay", termTaxonomyVo);

			model.put("baseInfo", baseInfoVo);
			model.put("article", articleService.getArticleInfo(articleId));

			HcmsHomePageVo homePageVo = new HcmsHomePageVo();
			{
				homePageVo.setWebPageNavs(termTaxonomyService.loadSysNavs());
			}
			model.put("homePageInfo", homePageVo);

			termIds.parallelStream().forEach(termId -> {
				HcmsTermsVo hcmsTermsVo = termsService.getHcmsTermsById(termId);
				if (CommonUtil.isEmpty(hcmsTermsVo)) {
					return;
				}

				HcmsTermsVo termsVo = termsService.getHcmsTermsByCode(hcmsTermsVo.getTermCode());
				model.put("term", termsVo);
				model.put("basePath", systemEnvConfigProperties.getStaticHtmlDomainName());
				model.put("recommendArticle", articleService.recommendArticle(termsVo.getId()));

				String staticUrl = "cms-static" + "/" + DateUtil.now4yyyyMMdd() + "/"
						+ hcmsTermTaxonomyVo.getTermTayCode().trim() + "/" + hcmsTermsVo.getTermCode().trim() + "/"
						+ articleId + ".html";
				try {
					Resource resource = new ClassPathResource("/templates/article");
					File templateFolder = resource.getFile();
					// 填充模板数据、压缩数据
					String html = FreemakUtil.process(templateFolder, "article_detail.ftl", model);
					String htmlPath = systemEnvConfigProperties.getStaticHtmlPath() + "/" + staticUrl;
					// 静态化完成
					FileUtil.writer(htmlPath, html, true);

					ArticleDomain articleDomain = articleRepository.findOne(articleId.trim());
					articleDomain.setStaticizeUri(staticUrl);
					articleRepository.save(articleDomain);
				} catch (Exception e) {
					log.error(e.getMessage(), e);
				}
			});
		}
	}

	@Override
	public void staticArticleAll(boolean cover) {
		taskExecutor.execute(new Runnable() {

			@Override
			public void run() {
				AtomicInteger pageIndex = new AtomicInteger(0);
				AtomicBoolean hasNext = new AtomicBoolean(true);
				do {
					QArticleDomain qArticleDomain = QArticleDomain.articleDomain;
					List<ArticleDomain> content = null;
					if (cover) {
						content = articleRepository
								.findAll(qArticleDomain.status.eq(DataStatusDef.ENABLE),
										new QPageRequest(pageIndex.get(), PAGE_SIZE, qArticleDomain.createTime.desc()))
								.getContent();
					} else {
						content = articleRepository
								.findAll(
										qArticleDomain.status.eq(DataStatusDef.ENABLE)
												.and(qArticleDomain.staticizeUri.isNull()),
										new QPageRequest(pageIndex.get(), PAGE_SIZE, qArticleDomain.createTime.desc()))
								.getContent();
					}

					if (CommonUtil.isEmpty(content)) {
						hasNext.set(false);
					}
					content.parallelStream().forEach(article -> {
						try {
							staticArticle(article.getId());
						} catch (Exception e) {
							log.error("静态化文件失败:{}", article.getId());
						}
					});

					log.info("静态生成文件第{}页数据,每页展示{}", pageIndex.get(), PAGE_SIZE);
					pageIndex.incrementAndGet();
				} while (hasNext.get());
				log.info("{}静态文件生成完成", DateUtil.now4yyyyMMddhhmm());
			}
		});
	}

}
